home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / PC.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  8KB  |  390 lines

  1. /* OS- and machine-dependent stuff for IBM-PC running MS-DOS and Turbo-C */
  2. #include <stdio.h>
  3. #include <dir.h>
  4. #include <dos.h>
  5. #include <io.h>
  6. #include <sys/stat.h>
  7. #include <string.h>
  8. #include <process.h>
  9. #include <fcntl.h>
  10. #include <alloc.h>
  11. #include "global.h"
  12. #include "mbuf.h"
  13. #include "internet.h"
  14. #include "iface.h"
  15. #include "cmdparse.h"
  16. #include "pc.h"
  17. #include "proc.h"
  18.  
  19. static int kbchar __ARGS((void));
  20. static void kbint __ARGS((void));
  21.  
  22. unsigned _stklen = 8192;
  23. int Tick;
  24.  
  25. /* This flag is set by setirq() if IRQ 8-15 is used, indicating
  26.  * that the machine is a PC/AT with a second 8259 interrupt controller.
  27.  * If this flag is set, the interrupt return code in pcgen.asm will
  28.  * send an End of Interrupt command to the second 8259 as well as the
  29.  * first.
  30.  */
  31. char Isat;
  32.  
  33. /* Interface list header */
  34. struct iface *Ifaces;
  35.  
  36. static char Ttbuf[BUFSIZ];
  37. static int saved_break;
  38.  
  39. /* Keyboard input buffer */
  40. #define    KBSIZE    256
  41. static struct {
  42.     char buf[KBSIZE];
  43.     char *wp;
  44.     char *rp;
  45.     int cnt;
  46. } Keyboard;
  47.  
  48. int
  49. errhandler(errval,ax,bp,si)
  50. int errval,ax,bp,si;
  51. {
  52.     return 3;    /* Fail the system call */
  53. }
  54.  
  55. /* Called at startup time to set up console I/O, memory heap */
  56. void
  57. ioinit(mem)
  58. int32 mem;
  59. {
  60. #ifndef __TURBOC__
  61.     struct sgttyb ttybuf;
  62. #endif
  63.     /* Ignore ctrl-breaks */
  64.     setvect(0x23,nullvec);
  65.  
  66.     /* Fail all I/O errors */
  67.     harderr(errhandler);
  68.  
  69.     /* Save these two file table entries for something more useful */
  70.     fclose(stdaux);
  71. #ifdef __TURBOC__
  72.     fclose(stdprn);
  73. #else
  74.     fclose(stdprt);
  75. #endif
  76.  
  77.     /* Interrupts use a special stack deep in data space.
  78.      * Calls to sbrk() (invoked by malloc when it needs more memory
  79.      * from the system) at interrupt time will fail because sbrk()
  80.      * will think that the stack has overwritten the heap. So
  81.      * grab all the memory we can now for the heap so that malloc
  82.      * won't have to call sbrk and alloc_mbuf() won't fail unnecessarily
  83.      * at interrupt time.
  84.      */
  85. #ifdef    LARGEDATA
  86.     grabcore(mem);
  87. #else
  88.     grabcore(mem);
  89. #endif
  90.  
  91.     setbuf(stdout,Ttbuf);
  92. #ifdef __TURBOC__
  93.     saved_break = getcbrk();
  94.     setcbrk(0);
  95.     ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff | 0x20);  /* put stdout in raw mode */
  96. #else
  97.     /* Put display in raw mode. Note that this breaks tab expansion,
  98.      * so you need to run NANSI.SYS or equivalent.
  99.      */
  100.     ioctl(1,TIOCGETP,&ttybuf);
  101.     ttybuf.sg_flags = RAW;
  102.     ioctl(1,TIOCSETP,&ttybuf);
  103. #endif
  104.     /* Link timer handler into timer interrupt chain */
  105.     chtimer(btick);
  106.  
  107.     /* Find out what multitasker we're running under, if any */
  108.     chktasker();
  109.  
  110.     /* Initialize keyboard queue */
  111.     Keyboard.rp = Keyboard.wp = Keyboard.buf;
  112.  
  113. }
  114. /* Called just before exiting to restore console state */
  115. void
  116. iostop()
  117. {
  118. #ifndef __TURBOC__
  119.     struct sgttyb ttybuf;
  120. #endif
  121.  
  122.     setbuf(stdout,NULLCHAR);
  123. #ifdef __TURBOC__
  124.     setcbrk(saved_break);
  125.     ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff & ~0x20);  /* put stdout in cooked mode */
  126. #else
  127.     ioctl(1,TIOCGETP,&ttybuf);
  128.     ttybuf.sg_flags &= ~RAW;
  129.     ioctl(1,TIOCSETP,&ttybuf);
  130. #endif
  131.     while(Ifaces != NULLIF){
  132.         if(Ifaces->stop != NULLFP)
  133.             (*Ifaces->stop)(Ifaces);
  134.         Ifaces = Ifaces->next;
  135.     }
  136.     /* Unlink timer handler from timer chain */
  137.     uchtimer();
  138. }
  139. /* Spawn subshell */
  140. int
  141. doshell(argc,argv,p)
  142. int argc;
  143. char *argv[];
  144. void *p;
  145. {
  146.     char *command;
  147.     int ret;
  148. #ifdef __TURBOC__
  149.  
  150.     ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff & ~0x20);  /* put stdout in cooked mode */
  151.     if((command = getenv("COMSPEC")) == NULLCHAR)
  152.         command = "/COMMAND.COM";
  153.     ret = spawnv(P_WAIT,command,argv);
  154.  
  155.     ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff | 0x20);  /* put stdout in raw mode */
  156.     return ret;
  157. #else
  158.     struct sgttyb ttybuf,ttysav;
  159.  
  160.     ioctl(1,TIOCGETP,&ttysav);
  161.     ioctl(1,TIOCGETP,&ttybuf);
  162.     ttybuf.sg_flags &= ~RAW;
  163.     ioctl(1,TIOCSETP,&ttybuf);
  164.  
  165.     if((command = getenv("COMSPEC")) == NULLCHAR)
  166.         command = "/COMMAND.COM";
  167.     ret = fexecl(command,command,NULLCHAR);
  168.     ioctl(1,TIOCSETP,&ttysav);
  169.     if(ret == -1)
  170.         return -1;
  171.     else
  172.         return wait();
  173. #endif
  174. }
  175.  
  176. /* Keyboard interrupt handler */
  177. static void
  178. kbint()
  179. {
  180.     int sig = 0;
  181.     int c;
  182.  
  183.     while((c = kbraw()) != -1 && Keyboard.cnt < KBSIZE){
  184.         sig = 1;
  185.         *Keyboard.wp++ = c;
  186.         if(Keyboard.wp == &Keyboard.buf[KBSIZE])
  187.             Keyboard.wp = Keyboard.buf;
  188.         Keyboard.cnt++;
  189.     }
  190.     if(sig){
  191.         psignal(&Keyboard,1);
  192.     }
  193. }
  194. static int
  195. kbchar()
  196. {
  197.     char i_state;
  198.     char c;
  199.  
  200.     i_state = dirps();
  201.     while(Keyboard.cnt == 0)
  202.         pwait(&Keyboard);
  203.     c = *Keyboard.rp++;
  204.     if(Keyboard.rp == &Keyboard.buf[KBSIZE])
  205.         Keyboard.rp = Keyboard.buf;
  206.     Keyboard.cnt--;
  207.     restore(i_state);
  208.     return c;
  209. }
  210. /* Read characters from the keyboard, translating them to "real" ASCII.
  211.  * If none are ready, block. The F-10 key is special; translate it to -2.
  212.  */
  213. int
  214. kbread()
  215. {
  216.     int c;
  217.  
  218.     if((c = kbchar()) == 0){
  219.         /* Lead-in to a special char */
  220.         c = kbchar();
  221.         switch(c){
  222.         case 3:        /* NULL (bizzare!) */
  223.             c = 0;
  224.             break;
  225.         case 68:    /* F-10 key (used as command-mode escape) */
  226.             c = -2;
  227.             break;
  228.         case 83:    /* DEL key */
  229.             c = 0x7f;
  230.             break;
  231.         default:    /* Dunno what it is */
  232.             c = -1;
  233.         }
  234.     }
  235.     return c;
  236. }
  237.  
  238. /* Called from the timer routine on each tick */
  239. void
  240. systick()
  241. {
  242.     /* Tickle the keyboard interrupt. This nonsense is
  243.      * necessary because there's no way to get a hardware interrupt
  244.      * from the BIOS.
  245.      */
  246.     kbint();
  247.  
  248.     /* Flush out console. This gains efficiency in telnet
  249.      * since it only handles a character at a time, at the cost
  250.      * of a slight echo delay.
  251.      */
  252.     fflush(stdout);
  253. }
  254. /* Install hardware interrupt handler.
  255.  * Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
  256.  * Note that bus line IRQ2 maps to IRQ9 on the AT
  257.  */
  258. int
  259. setirq(irq,handler)
  260. unsigned irq;
  261. INTERRUPT (*handler)();
  262. {
  263.     /* Set interrupt vector */
  264.     if(irq < 8){
  265.         setvect(8+irq,handler);
  266.     } else if(irq < 16){
  267.         Isat = 1;
  268.         setvect(0x70 + irq - 8,handler);
  269.     } else {
  270.         return -1;
  271.     }
  272.     return 0;
  273. }
  274. /* Return pointer to hardware interrupt handler.
  275.  * Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
  276.  */
  277. INTERRUPT
  278. (*getirq(irq))()
  279. unsigned int irq;
  280. {
  281.     /* Set interrupt vector */
  282.     if(irq < 8){
  283.         return getvect(8+irq);
  284.     } else if(irq < 16){
  285.         return getvect(0x70 + irq - 8);
  286.     } else {
  287.         return NULLVIFP;
  288.     }
  289. }
  290. /* Disable hardware interrupt */
  291. int
  292. maskoff(irq)
  293. unsigned irq;
  294. {
  295.     if(irq < 8){
  296.         setbit(0x21,(char)(1<<irq));
  297.     } else if(irq < 16){
  298.         irq -= 8;
  299.         setbit(0xa1,(char)(1<<irq));
  300.     } else {
  301.         return -1;
  302.     }
  303.     return 0;
  304. }
  305. /* Enable hardware interrupt */
  306. int
  307. maskon(irq)
  308. unsigned irq;
  309.  {
  310.     if(irq < 8){
  311.         clrbit(0x21,(char)(1<<irq));
  312.     } else if(irq < 16){
  313.         irq -= 8;
  314.         clrbit(0xa1,(char)(1<<irq));
  315.     } else {
  316.         return -1;
  317.     }
  318.     return 0;
  319. }
  320. /* Return 1 if specified interrupt is enabled, 0 if not, -1 if invalid */
  321. int
  322. getmask(irq)
  323. unsigned irq;
  324. {
  325.     if(irq < 8)
  326.         return (inportb(0x21) & (1 << irq)) ? 0 : 1;
  327.     else if(irq < 16){
  328.         irq -= 8;
  329.         return (inportb(0xa1) & (1 << irq)) ? 0 : 1;
  330.     } else
  331.         return -1;
  332. }
  333. /* Called from assembler stub linked to BIOS interrupt 1C, called on each
  334.  * hardware clock tick. Signal a clock tick to the timer process.
  335.  */
  336. void
  337. ctick()
  338. {
  339.     Tick++;
  340.     psignal(&Tick,1);
  341. }
  342. /* Set bit(s) in I/O port */
  343. void
  344. setbit(port,bits)
  345. unsigned port;
  346. char bits;
  347. {
  348.     outportb(port,(char)inportb(port)|bits);
  349. }
  350. /* Clear bit(s) in I/O port */
  351. void
  352. clrbit(port,bits)
  353. unsigned port;
  354. char bits;
  355. {
  356.     outportb(port,(char)(inportb(port) & ~bits));
  357. }
  358. /* Convert a pointer to a long integer */
  359. long
  360. ptol(p)
  361. void *p;
  362. {
  363.     long x;
  364.  
  365.     x = FP_OFF(p);
  366. #ifdef    LARGEDATA
  367.     x |= (long)FP_SEG(p) << 16;
  368. #endif
  369.     return x;
  370. }
  371. void *
  372. ltop(l)
  373. long l;
  374. {
  375.     register unsigned seg,offset;
  376.  
  377.     seg = l >> 16;
  378.     offset = l;
  379.     return MK_FP(seg,offset);
  380. }
  381. void
  382. sysreset()
  383. {
  384.     void (*foo) __ARGS((void));
  385.  
  386.     foo = MK_FP(0xffff,0);    /* FFFF:0000 is hardware reset vector */
  387.     (*foo)();
  388. }
  389.  
  390.